package co.yixiang.hw.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import co.yixiang.exception.EntityExistException;
import co.yixiang.hw.domain.*;
import co.yixiang.hw.repository.YxStoreOrderCartInfoRepository;
import co.yixiang.hw.service.YxStoreCouponUserService;
import co.yixiang.hw.service.YxStoreOrderCartInfoService;
import co.yixiang.hw.service.YxStoreOrderStatusService;
import co.yixiang.utils.*;
import co.yixiang.hw.repository.YxStoreOrderRepository;
import co.yixiang.hw.service.YxStoreOrderService;
import co.yixiang.hw.service.dto.YxStoreOrderDto;
import co.yixiang.hw.service.dto.YxStoreOrderQueryCriteria;
import co.yixiang.hw.service.mapper.YxStoreOrderMapper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qiniu.util.Md5;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.math.BigDecimal;
import java.util.*;
import java.io.IOException;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

/**
* @author Walert
* @date 2020-02-13
*/
@Service
//@CacheConfig(cacheNames = "yxStoreOrder")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class YxStoreOrderServiceImpl implements YxStoreOrderService {

    @Resource
    private YxStoreOrderRepository yxStoreOrderRepository;
    @Resource
    private YxStoreOrderMapper yxStoreOrderMapper;
    @Resource
    private YxStoreOrderCartInfoRepository yxStoreOrderCartInfoRepository;

    @Autowired
    private YxStoreCouponUserService couponUserService;

    @Autowired
    private YxStoreOrderCartInfoService orderCartInfoService;

    @Autowired
    private YxStoreOrderStatusService orderStatusService;

    @Override
    //@Cacheable
    public Map<String,Object> queryAll(YxStoreOrderQueryCriteria criteria, Pageable pageable){

        Page<YxStoreOrder> page = yxStoreOrderRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        List<Object> resultList = new ArrayList<>(page.getContent().size());
        for (YxStoreOrder order : page.getContent()) {
            JSONObject object = new JSONObject();
            object.put("id",order.getId());
            object.put("orderId",order.getOrderId());
            object.put("addTime", DateUtil.format(DateUtil.date(order.getAddTime()*1000L),DatePattern.NORM_DATETIME_FORMAT));
            object.put("payStatus",order.getPaid());
            object.put("unique",order.getUnique());

            List<YxStoreOrderCartInfo> orderCartInfoList = yxStoreOrderCartInfoRepository.findByOid(order.getId());
            JSONArray goodsList = new JSONArray(orderCartInfoList.size());
            for (YxStoreOrderCartInfo orderCartInfo : orderCartInfoList) {

                JSONObject cartInfoObj = commonCartInfo(orderCartInfo);

//                JSONObject cartInfo = JSONObject.parseObject(orderCartInfo.getCartInfo());
//                cartInfoObj.put("goodsId",orderCartInfo.getProductId());
//                cartInfoObj.put("cartNum",cartInfo.getInteger("cartNum"));
//                JSONObject productInfo = cartInfo.getJSONObject("productInfo");
//                cartInfoObj.put("goodsName",productInfo.getString("storeInfo"));
//                cartInfoObj.put("goodsImage",productInfo.getString("image"));
//                cartInfoObj.put("goodsPrice",productInfo.getString("price"));
//                cartInfoObj.put("goodsOtPrice",productInfo.getString("otPrice"));

                goodsList.add(cartInfoObj);
            }
            object.put("goodsList",goodsList);
            //订单状态
            String orderStatusStr = OrderUtil.orderStatusStr(order.getPaid()
                    ,order.getStatus(),order.getShippingType()
                    ,order.getRefundStatus());
            int orderStatus = OrderUtil.orderStatus(order.getPaid()
                    , order.getStatus()
                    , order.getRefundStatus());
            object.put("status",orderStatusStr);
            object.put("orderStatus",orderStatus);
            object.put("transId",order.getTransId());

            if(order.getIsRoot() == 1 && order.getPaid() == 1){

            }else if(order.getIsRoot() == 0 && order.getParentId() != null && order.getPaid() == 0){

            }else {
                resultList.add(object);
            }
        }

        return PageUtil.toPageHadTotalPage(resultList,page.getTotalElements(),page.getTotalPages());
    }

    @Override
    //@Cacheable
    public List<YxStoreOrderDto> queryAll(YxStoreOrderQueryCriteria criteria){
        return yxStoreOrderMapper.toDto(yxStoreOrderRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    //@Cacheable(key = "#p0")
    public JSONObject findById(Integer id) {
        YxStoreOrder order = yxStoreOrderRepository.findById(id).orElseGet(YxStoreOrder::new);
        return packingDetailsInfo(order);
    }

    @Override
    public JSONObject findByUniqueNo(String unique) {
        YxStoreOrder order = yxStoreOrderRepository.findByUnique(unique).orElseGet(YxStoreOrder::new);
        return packingDetailsInfo(order);
    }

    private JSONObject commonCartInfo(YxStoreOrderCartInfo orderCartInfo){
        JSONObject cartInfoObj = new JSONObject();
        JSONObject cartInfo = JSONObject.parseObject(orderCartInfo.getCartInfo());
        cartInfoObj.put("goodsId",orderCartInfo.getProductId());
        Integer cartNum = cartInfo.getInteger("cartNum");
        cartInfoObj.put("cartNum",cartInfo.getInteger("cartNum"));
        JSONObject productInfo = cartInfo.getJSONObject("productInfo");
        cartInfoObj.put("goodsName",productInfo.getString("storeInfo"));
        cartInfoObj.put("goodsImage",productInfo.getString("image"));
        cartInfoObj.put("goodsPrice",productInfo.getString("price"));
        cartInfoObj.put("goodsOtPrice",productInfo.getString("otPrice"));
        BigDecimal otPrice = productInfo.getBigDecimal("otPrice");
        cartInfoObj.put("amount",otPrice.multiply(new BigDecimal(cartNum)));

        JSONObject coupon = cartInfo.getJSONObject("coupon");
        if(coupon != null ){
            cartInfoObj.put("coupon",coupon);
        }

        return cartInfoObj;
    }
    /**
     * 获取订单明细信息
     * @param order
     * @return
     */
    private JSONObject packingDetailsInfo(YxStoreOrder order){

        ValidationUtil.isNull(order.getId(),"YxStoreOrder","id",order.getId());

        JSONObject result = new JSONObject();
        result.put("id",order.getId());
        result.put("orderId",order.getOrderId());
        result.put("realName",order.getRealName());
        result.put("userAddress",order.getUserAddress());
        result.put("userPhone",order.getUserPhone());
        result.put("payStatus",order.getPaid());
        result.put("addTime",DateUtil.format(DateUtil.date(order.getAddTime()*1000L),DatePattern.NORM_DATETIME_FORMAT));
        if(order.getPayTime() != null && order.getPayTime() > 0){
            result.put("payTime",DateUtil.format(DateUtil.date(order.getPayTime()*1000L),DatePattern.NORM_DATETIME_FORMAT));
        }else{
            result.put("payTime","");
        }
        result.put("deliveryId",order.getDeliveryId());//运单号
        result.put("deliveryName",order.getDeliveryName());//快递公司
        result.put("payPrice",order.getPayPrice());//实际支付金额
        result.put("couponPrice",order.getCouponPrice());
        result.put("mark",order.getMark());
        result.put("remark",order.getRemark());
        BigDecimal goodsAmount = BigDecimal.ZERO;
        List<YxStoreOrderCartInfo> orderCartInfoList = yxStoreOrderCartInfoRepository.findByOid(order.getId());
        JSONArray goodsList = new JSONArray(orderCartInfoList.size());
        for (YxStoreOrderCartInfo orderCartInfo : orderCartInfoList) {

            JSONObject cartInfoObj = commonCartInfo(orderCartInfo);
//            JSONObject cartInfo = JSONObject.parseObject(orderCartInfo.getCartInfo());
//            cartInfoObj.put("goodsId",orderCartInfo.getProductId());
//            Integer cartNum = cartInfo.getInteger("cartNum");
//            cartInfoObj.put("cartNum",cartInfo.getInteger("cartNum"));
//            JSONObject productInfo = cartInfo.getJSONObject("productInfo");
//            cartInfoObj.put("goodsName",productInfo.getString("storeInfo"));
//            cartInfoObj.put("goodsImage",productInfo.getString("image"));
//            cartInfoObj.put("goodsPrice",productInfo.getString("price"));
//            cartInfoObj.put("goodsOtPrice",productInfo.getString("otPrice"));

            goodsAmount = goodsAmount.add(cartInfoObj.getBigDecimal("amount"));

            goodsList.add(cartInfoObj);
        }
        result.put("goodsAmount",goodsAmount);//商品总额
        result.put("goodsList",goodsList);
        //订单状态
        String orderStatusStr = OrderUtil.orderStatusStr(order.getPaid()
                ,order.getStatus(),order.getShippingType()
                ,order.getRefundStatus());
        result.put("status",orderStatusStr);
        int orderStatus = OrderUtil.orderStatus(order.getPaid()
                , order.getStatus()
                , order.getRefundStatus());
        result.put("orderStatus",orderStatus);
        result.put("transId",order.getTransId());
        if(orderStatus == 6){
            List<Integer> list = yxStoreOrderRepository.findOrderEndTime(order.getId());
            if(list != null && list.size() > 0){
                result.put("endTime",DateUtil.format(DateUtil.date(list.get(0)*1000L),DatePattern.NORM_DATETIME_FORMAT));
            }
        }
        return result;
    }

    @Override
    //@CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public YxStoreOrderDto create(YxStoreOrder resources) throws Exception {
        resources.setUnique(EncryptUtils.desEncrypt(resources.getOrderId()));
        if(yxStoreOrderRepository.findByUnique(resources.getUnique()).isPresent()){
            throw new EntityExistException(YxStoreOrder.class,"unique",resources.getUnique());
        }
        return yxStoreOrderMapper.toDto(yxStoreOrderRepository.save(resources));
    }

    @Override
    //@CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void update(YxStoreOrder resources) {
        YxStoreOrder yxStoreOrder = yxStoreOrderRepository.findById(resources.getId()).orElseGet(YxStoreOrder::new);
        ValidationUtil.isNull( yxStoreOrder.getId(),"YxStoreOrder","id",resources.getId());
        YxStoreOrder yxStoreOrder1 = yxStoreOrderRepository.findByUnique(resources.getUnique()).orElseGet(YxStoreOrder::new);
        if(yxStoreOrder1 != null && !yxStoreOrder1.getId().equals(yxStoreOrder.getId())){
            throw new EntityExistException(YxStoreOrder.class,"unique",resources.getUnique());
        }
        yxStoreOrder.copy(resources);
        yxStoreOrderRepository.save(yxStoreOrder);
    }

    @Override
    //@CacheEvict(allEntries = true)
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            yxStoreOrderRepository.deleteById(id);
        }
    }

    @Override
    public YxStoreOrder findByIdAndIsDel(Integer id) {
        return yxStoreOrderRepository.findByIdAndIsDel(id,0);
    }

    @Override
    public void createSubOrder(YxStoreOrderDto parent, JSONArray goodsList, Map<Integer, List<YxStoreProduct>> productMap) throws Exception {
        YxStoreOrder resources = yxStoreOrderMapper.toEntity(parent);
        int size = goodsList.size();
        Map<Integer,JSONObject> goodsMap = new HashMap<>();
        for (int i = 0; i < size; i++) {
            JSONObject goodsObject = goodsList.getJSONObject(i);
            Integer productId = goodsObject.getInteger("productId");
            goodsMap.put(productId,goodsObject);
        }
        for(Map.Entry<Integer,List<YxStoreProduct>> entry : productMap.entrySet()){
            List<YxStoreProduct> list = entry.getValue();
            JSONArray _goodsList = new JSONArray(list.size());
            BigDecimal totalPrice = BigDecimal.ZERO;
            Integer totalNum = 0;
            BigDecimal couponPrice = BigDecimal.ZERO;
            for (YxStoreProduct yxStoreProduct : list) {
                JSONObject jsonObject = goodsMap.get(yxStoreProduct.getId());
                _goodsList.add(jsonObject);
                Integer cartNum = jsonObject.getInteger("cartNum");
                totalPrice = totalPrice.add(yxStoreProduct.getPrice().multiply(new BigDecimal(cartNum)));
                totalNum += cartNum;
                JSONObject coupon = jsonObject.getJSONObject("coupon");
                if(coupon!= null){
                    couponPrice = couponPrice.add(coupon.getBigDecimal("couponPrice"));
                }
            }
            BigDecimal payPrice = totalPrice;
            if(couponPrice.compareTo(BigDecimal.ZERO) == 1){
                payPrice = totalPrice.subtract(couponPrice);
            }
            resources.setId(null);
            resources.setIsRoot(0);
            resources.setOrderId(parent.getOrderId() + "-" + entry.getKey());
            resources.setTotalNum(totalNum);
            resources.setTotalPrice(totalPrice);
            resources.setCouponPrice(couponPrice);
            resources.setPayPrice(payPrice);
            resources.setParentId(parent.getId());
            YxStoreOrderDto yxStoreOrderDto = this.create(resources);

            orderCartInfoService.saveOrderCartInfo(yxStoreOrderDto,_goodsList);

            //生成订单状态
            orderStatusService.asyncCreate(yxStoreOrderDto.getId(),"cache_key_create_order","订单生成");
        }
    }

    @Override
    public List<YxStoreOrder> getByParentId(Integer parentId) {
        return yxStoreOrderRepository.getByParentId(parentId);
    }
}